
#include "KEYPAD.h"

uint8_t KEYPAD_INT_MARK = 0;

// 按键表
const uint8_t KEYVALUE_TABLE[4][4] = {'7', '8', '9', '/',
                                      '4', '5', '6', '*',
                                      '1', '2', '3', '-',
                                      'C', '0', '=', '+'};

void KEYPAD_INT_ON()
{
    EXTI->PR |= (1 << 4);
    EXTI->IMR |= (1 << 4);
    EXTI->PR |= (1 << 5);
    EXTI->IMR |= (1 << 5);
    EXTI->PR |= (1 << 6);
    EXTI->IMR |= (1 << 6);
    EXTI->PR |= (1 << 7);
    EXTI->IMR |= (1 << 7);
}
void KEYPAD_INT_OFF()
{
    EXTI->IMR &= ~(1 << 4);
    EXTI->IMR &= ~(1 << 5);
    EXTI->IMR &= ~(1 << 6);
    EXTI->IMR &= ~(1 << 7);
}
void KEYPAD_Init(void)
{
    KEYPAD_IO_Init();
    KEYPAD_INT_Init();
    KEYPAD_INT_MARK = 0;
}
void KEYPAD_IO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // 时钟开启放到中断初始化中
    GPIO_InitStructure.GPIO_Pin = KEYPAD_A | KEYPAD_B | KEYPAD_C | KEYPAD_D;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
    GPIO_Init(KEYPAD_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEYPAD_1 | KEYPAD_2 | KEYPAD_3 | KEYPAD_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(KEYPAD_PORT, &GPIO_InitStructure);

    GPIO_SetBits(KEYPAD_PORT, KEYPAD_A | KEYPAD_B | KEYPAD_C | KEYPAD_D);
    GPIO_ResetBits(KEYPAD_PORT, KEYPAD_1 | KEYPAD_2 | KEYPAD_3 | KEYPAD_4);
}
/**
 * @brief 按键反转
 */
void KEYPAD_IO_Rever(void)
{

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = KEYPAD_1 | KEYPAD_2 | KEYPAD_3 | KEYPAD_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
    GPIO_Init(KEYPAD_PORT, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = KEYPAD_A | KEYPAD_B | KEYPAD_C | KEYPAD_D;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(KEYPAD_PORT, &GPIO_InitStructure);
    GPIO_SetBits(KEYPAD_PORT, KEYPAD_1 | KEYPAD_2 | KEYPAD_3 | KEYPAD_4);
    GPIO_ResetBits(KEYPAD_PORT, KEYPAD_A | KEYPAD_B | KEYPAD_C | KEYPAD_D);
}

void KEYPAD_Scan(void)
{
    uint8_t k = 0;
    if (KEYPAD_INT_MARK)
    {
        printf("KEYPAD_INT_MARK = %d \r\n", KEYPAD_INT_MARK);
        KEYPAD_INT_MARK = 0;
        k = KEYPAD_ReadValue();
        if (k)
        {
            printf("KEY VALUE = %c \r\n", k);
        }
    }
}
/**
 * 按下则返回字符码;没按返回0
 */
uint8_t KEYPAD_ReadValue(void)
{
    uint8_t line = 0; // 按键表-行
    uint8_t row = 0;  // 按键表-列
    uint8_t temp = 0;
    if (!GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_A) ||
        !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_B) ||
        !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_C) ||
        !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_D))
    {
        delay_ms(20);
        if (!GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_A) ||
            !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_B) ||
            !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_C) ||
            !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_D))
        {

            temp = (GPIO_ReadInputData(KEYPAD_PORT) & 0xFF) >> 4; // PA4~PA7(有1bit为0)
            temp = (~temp) & 0x0F;
            while (temp > 1)
            {
                temp = temp >> 1;
                line++;
            }
            KEYPAD_INT_OFF();                                // 关闭中断
            KEYPAD_IO_Rever();                               // 按键反转
            temp = (GPIO_ReadInputData(KEYPAD_PORT) & 0xFF); // PA0~PA3(有1bit为0)
            temp = ((~temp) & 0x0F);
            while (temp > 1)
            {
                temp = temp >> 1;
                row++;
            }
            while (!GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_1) ||
                   !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_2) ||
                   !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_3) ||
                   !GPIO_ReadInputDataBit(KEYPAD_PORT, KEYPAD_4))
                ;
            delay_ms(10);
            KEYPAD_INT_ON();
            KEYPAD_IO_Init();
            return KEYVALUE_TABLE[line][row];
        }
    }
    return 0;
}

void KEYPAD_INT_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 复用

    // PA4
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);
    EXTI_InitStructure.EXTI_Line = EXTI_Line4;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿
    EXTI_Init(&EXTI_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;          // 中断请求通道选择
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // 中断请求通道使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 相应优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        // 子优先级
    NVIC_Init(&NVIC_InitStructure);
    // PA5
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);
    EXTI_InitStructure.EXTI_Line = EXTI_Line5;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿
    EXTI_Init(&EXTI_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;        // 中断请求通道选择
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // 中断请求通道使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 相应优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        // 抢占优先级
    NVIC_Init(&NVIC_InitStructure);
    // PA6
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);
    EXTI_InitStructure.EXTI_Line = EXTI_Line6;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿
    EXTI_Init(&EXTI_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;        // 中断请求通道选择
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // 中断请求通道使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 相应优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        // 抢占优先级
    NVIC_Init(&NVIC_InitStructure);
    // PA7
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource7);
    EXTI_InitStructure.EXTI_Line = EXTI_Line7;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿
    EXTI_Init(&EXTI_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;        // 中断请求通道选择
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // 中断请求通道使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 相应优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        // 抢占优先级
    NVIC_Init(&NVIC_InitStructure);
}

void EXTI4_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line4) != RESET)
    {
        KEYPAD_INT_MARK = 1;
        EXTI_ClearFlag(EXTI_Line4);
    }
}

void EXTI9_5_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line5) != RESET)
    {
        KEYPAD_INT_MARK = 2;
        EXTI_ClearFlag(EXTI_Line5);
    }

    if (EXTI_GetITStatus(EXTI_Line6) != RESET)
    {
        KEYPAD_INT_MARK = 3;
        EXTI_ClearFlag(EXTI_Line6);
    }

    if (EXTI_GetITStatus(EXTI_Line7) != RESET)
    {
        KEYPAD_INT_MARK = 4;
        EXTI_ClearFlag(EXTI_Line7);
    }
}
